#pragma once

#include "base_noncopyable.h"
#include <spdlog/spdlog.h>

namespace El {
namespace Base {

// 自定义日志级别枚举
enum class LogLevel {
    BASE_TRACE,    // 跟踪
    BASE_DEBUG,    // 调试
    BASE_INFO,     // 信息
    BASE_WARN,     // 警告
    BASE_ERROR,    // 错误
    BASE_CRITICAL, // 严重
    BASE_OFF       // 关闭
};

class Log {
    DISALLOW_COPY_AND_MOVE(Log);

public:
    static Log &GetInstance();
    
    Log() = default;
    
    ~Log() = default;

    bool init(const std::string &filename,
              const std::string &loggerName,
              int32_t max_size,
              int32_t max_files);

    // 使用自定义日志级别的接口
    void setLogLevel(LogLevel level);

    // 设置日志级别
    // trace, debug, info, warn, error, critical, off
    void setLogLevel(const std::string level);

    // 获取当前日志级别
    LogLevel getLogLevel() const;

    // 控制是否写文件
    void enableFileLogging(bool enable);
    bool isFileLoggingEnabled() const;

private:
    // 内部转换函数
    static spdlog::level::level_enum toSpdLogLevel(LogLevel level);
    static LogLevel fromSpdLogLevel(spdlog::level::level_enum level);
    void updateLoggers(); // 更新日志记录器
    LogLevel currentLevel{LogLevel::BASE_INFO}; // 保存当前日志级别
    bool fileLoggingEnabled_{false}; // 控制是否写文件，默认不写文件
    std::shared_ptr<spdlog::logger> fileLogger_; // 文件日志记录器
    std::shared_ptr<spdlog::logger> consoleLogger_; // 控制台日志记录器
    std::string logFilename_;
    std::string loggerName_;
    int32_t maxSize_;
    int32_t maxFiles_;
};

} // namespace Base
} // namespace El

// 宏定义日志打印
#define LOG_TRACE(...) SPDLOG_LOGGER_CALL(spdlog::default_logger_raw(), spdlog::level::trace, __VA_ARGS__)
#define LOG_DEBUG(...) SPDLOG_LOGGER_CALL(spdlog::default_logger_raw(), spdlog::level::debug, __VA_ARGS__)
#define LOG_INFO(...) SPDLOG_LOGGER_CALL(spdlog::default_logger_raw(), spdlog::level::info, __VA_ARGS__)
#define LOG_WARN(...) SPDLOG_LOGGER_CALL(spdlog::default_logger_raw(), spdlog::level::warn, __VA_ARGS__)
#define LOG_ERROR(...) SPDLOG_LOGGER_CALL(spdlog::default_logger_raw(), spdlog::level::err, __VA_ARGS__)
#define LOG_CRITICAL(...) SPDLOG_LOGGER_CALL(spdlog::default_logger_raw(), spdlog::level::critical, __VA_ARGS__)